# 从Django的数据库模块导入models类，用于定义数据库模型
from django.db import models
# 导入secrets模块，用于生成安全的随机数
import secrets
# 导入string模块，用于处理字符串
import string

# 定义一个名为城市的数据库模型，继承自models.Model
class City(models.Model):
    # 定义一个名为name的字符字段，最大长度为100，且唯一
    name = models.CharField(max_length=100, unique=True)

    # 定义一个特殊方法__str__，用于返回对象的字符串表示
    def __str__(self):
        return self.name

# 定义一个名为房间的数据库模型，继承自models.Model
class Room(models.Model):
    # 定义一个名为name的字符字段，最大长度为100
    name = models.CharField(max_length=100)
    # 定义一个外键字段city，关联到City模型，当关联的City对象被删除时，此记录也会被删除
    city = models.ForeignKey(City, on_delete=models.CASCADE)

    # 定义一个特殊方法__str__，用于返回对象的字符串表示
    def __str__(self):
        return f"{self.city.name} - {self.name}"

# 定义一个名为主机的数据库模型，继承自models.Model
class Host(models.Model):
    # 定义一个名为ip_address的通用IP地址字段，且唯一
    ip_address = models.GenericIPAddressField(unique=True)
    # 定义一个名为hostname的字符字段，最大长度为100，且唯一
    hostname = models.CharField(max_length=100, unique=True)
    # 定义一个外键字段city，关联到City模型，当关联的City对象被删除时，此记录的city字段置为null
    city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True)
    # 定义一个外键字段room，关联到Room模型，当关联的Room对象被删除时，此记录的room字段置为null
    room = models.ForeignKey(Room, on_delete=models.SET_NULL, null=True)
    # 定义一个名为root_password的文本字段，用于存储主机的root密码
    root_password = models.TextField()
    # 定义一个名为last_password_change的日期时间字段，每次保存对象时自动更新为当前时间
    last_password_change = models.DateTimeField(auto_now=True)
    # 定义一个名为is_alive的布尔字段，默认值为False，表示主机是否存活
    is_alive = models.BooleanField(default=False)

    # 定义一个方法generate_random_password，用于生成指定长度的随机密码，默认长度为16
    def generate_random_password(self, length=16):
        # 定义密码包含的字符集，包括字母、数字和标点符号
        characters = string.ascii_letters + string.digits + string.punctuation
        # 从字符集中随机选择字符，拼接成指定长度的字符串并返回
        return ''.join(secrets.choice(characters) for i in range(length))

    # 定义一个方法change_password，用于更改主机的root密码
    def change_password(self):
        # 保存旧密码
        old_password = self.root_password
        # 生成新密码
        new_password = self.generate_random_password()
        # 更新主机的root密码
        self.root_password = new_password
        # 保存主机对象
        self.save()

        # 创建一个PasswordChangeLog对象，记录密码更改信息
        PasswordChangeLog.objects.create(
            host=self,
            old_password=old_password,
            new_password=new_password
        )

        # 返回新密码
        return new_password

    # 定义一个特殊方法__str__，用于返回对象的字符串表示
    def __str__(self):
        return self.hostname

# 定义一个名为密码更改日志的数据库模型，继承自models.Model
class PasswordChangeLog(models.Model):
    # 定义一个外键字段host，关联到Host模型，当关联的Host对象被删除时，此记录也会被删除
    host = models.ForeignKey(Host, on_delete=models.CASCADE)
    # 定义一个名为timestamp的日期时间字段，创建对象时自动记录当前时间
    timestamp = models.DateTimeField(auto_now_add=True)
    # 定义一个名为old_password的文本字段，用于存储旧密码
    old_password = models.TextField()
    # 定义一个名为new_password的文本字段，用于存储新密码
    new_password = models.TextField()

    # 定义一个特殊方法__str__，用于返回对象的字符串表示
    def __str__(self):
        return f"{self.host.hostname} - {self.timestamp}"

# 定义一个名为主机计算统计的数据库模型，继承自models.Model
class HostCountStatistics(models.Model):
    # 定义一个外键字段city，关联到City模型，当关联的City对象被删除时，此记录也会被删除
    city = models.ForeignKey(City, on_delete=models.CASCADE)
    # 定义一个外键字段room，关联到Room模型，当关联的Room对象被删除时，此记录也会被删除
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    # 定义一个名为count的整数字段，用于记录主机数量，默认值为0
    count = models.IntegerField(default=0)
    # 定义一个名为date的日期字段，创建对象时自动记录当前日期
    date = models.DateField(auto_now_add=True)

    # 定义一个特殊方法__str__，用于返回对象的字符串表示
    def __str__(self):
        return f"{self.city.name} - {self.room.name} - {self.date}: {self.count}"